/*—————————————————————————————————————————————————————————— axios封装 ——————————————————————————————————————————————————————————*/

// 数据引入区
import axios from 'axios'
import { nowBaseUrl, addPending, removePending, httpErrorStatusHandle } from './apiToolkit' // 工具包
import { getToken, removeToken } from '@/utils/userMessage' // token操作函数
import commonConfig from '@/common/config/config' // 公共配置信息

// 路由hooks引入
// --------------------------------------------------------------------------------------------------------
import { useNavigate } from 'react-router-dom'

// antd组件
// --------------------------------------------------------------------------------------------------------
import { App } from 'antd'

// ts接口导入
import { MyAxiosType } from './interface'

// 结构公共配置
const { timeout, headers, tokenKey, PECodeShow, PEEerrorCodeShow, criticalCode, successCode } = commonConfig

// axios封装区
// ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
const useApi: MyAxiosType = (customOptions = {}) => {
  const { message } = App.useApp() // 使用app组件方法
  const navigate = useNavigate() // 路由操作方法

  /**
   * 声明一个新的axios请求实例
   * 每次重新创建一个新实例，一方面可以实现对应baseURL更新时的对应热更新，一方面可以保持每次请求的独立性
   * */
  // -----------------------------------------------------------------------------------------------------------
  const service = axios.create({
    baseURL: nowBaseUrl(), // 设置统一的请求前缀
    timeout, // 设置统一的超时时长
    headers // 设置统一的请求头
  })

  // 自定义配置
  // -----------------------------------------------------------------------------------------------------------
  const {
    requestCancel = false, // 是否开启取消重复请求, 默认为 false
    dataFormat = true, // 是否开启简洁的数据结构响应, 默认为true
    errorMessageShow = true, // 是否开启接口错误信息展示,默认为true
    codeMessageShow = false, // 是否开启code不为成功时时的信息提示, 默认为false
    isTokenHeader = true // 是否需要请求头携带token,默认为true
  } = customOptions

  // 请求拦截
  // -----------------------------------------------------------------------------------------------------------
  service.interceptors.request.use(
    config => {
      // 移除重复的请求
      removePending(config)

      // 根据是否开启重复请求，进行判断是否要重新添加请求
      // =========================================================================================
      requestCancel && addPending(config)

      // 如果需要携带token头，并且是兼容ssr的环境情况下，自动携带token
      // =========================================================================================
      if (isTokenHeader && typeof window !== 'undefined') {
        config.headers[tokenKey] = getToken()
      }

      // 弹出当前的请求内容
      return config
    },
    error => {
      // 进行提示错误信息
      message.error('请求发出出错！')
      return Promise.reject(error)
    }
  )

  // 响应拦截
  // -----------------------------------------------------------------------------------------------------------
  service.interceptors.response.use(
    response => {
      // 让当前请求成功后接口，从记录表中移除
      removePending(response.config)

      // 如果开启了code值大于某个时;并且也全局开启了前端code展示，若确实出现code大于的情况则进行后续逻辑操作
      // =========================================================================================
      if (codeMessageShow && PECodeShow && response?.data?.code > criticalCode) {
        // 查找当前的错误
        const errMessage = successCode[response.data.code] ?? `code值:${response.data.code}；发生未知错误！`

        // 进行提示错误信息
        message.error(errMessage)

        // code查询到了错误信息后，进行返回
        return Promise.reject(errMessage)
      }

      // 按照是否简洁返回的开关进行返回对应的数据结构
      // =========================================================================================
      return dataFormat ? response.data : response
    },
    error => {
      // 当存在请求错误的数据时，在记录表中移除在此接口信息
      error.config && removePending(error.config)

      // 错误信息展示变量
      let errMsg = error.message

      // 如果开启了 处理错误状态码，则进行对应的处理
      // =========================================================================================
      errorMessageShow && PEEerrorCodeShow && (errMsg = httpErrorStatusHandle(error))

      // 进行提示错误信息
      // =========================================================================================
      message.error(errMsg)

      // 根据当前的错误状态的额外展示内容
      // =========================================================================================
      switch (error.response.status) {
        // 如果是未登录
        case 413:
          // 删除当前的token
          removeToken()

          // 跳转到登陆页面
          navigate('/login', { replace: true })
          break

        default:
          break
      }

      // 弹出当前的错误信息
      // =========================================================================================
      return Promise.reject(error)
    }
  )

  return service
}

export default useApi
